package cn.lysoy.demo.utils;

import java.io.*;
import java.util.Collection;
import java.util.Map;

/**
 * @author SongYang
 */
public class ObjectUtil {
    /**
     * 判断对象或对象数组中每一个对象是否为空: 对象为null，字符序列长度为0，集合类、Map为empty
     *
     * @param obj
     * @return
     */
    public static boolean isNullOrEmpty(Object obj) {

        if (obj == null) {
            return true;
        }

        if (obj instanceof CharSequence) {
            return ((CharSequence) obj).length() == 0;
        }

        if (obj instanceof Collection) {
            return ((Collection) obj).isEmpty();
        }

        if (obj instanceof Map) {
            return ((Map) obj).isEmpty();
        }

        if (obj instanceof Object[]) {
            Object[] object = (Object[]) obj;
            if (object.length == 0) {
                return true;
            }
            boolean empty = true;
            for (int i = 0; i < object.length; i++) {
                if (!isNullOrEmpty(object[i])) {
                    empty = false;
                    break;
                }
            }
            return empty;
        }

        return false;
    }

    /**
     * Object 2 ByteArray
     * @param state is Object
     * @return ByteArray
     */
    public static byte[] object2Bytes(Object state) {
        ObjectOutputStream oos = null;
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
            oos = new ObjectOutputStream(baos);
            oos.writeObject(state);
            oos.flush();
            return baos.toByteArray();
        }
        catch (IOException e) {
            throw new IllegalArgumentException(e);
        }
        finally {
            if (oos != null) {
                try {
                    oos.close();
                }
                catch (IOException e) {
                    // eat it
                }
            }
        }
    }

    /**
     * ByteArray 2 Object
     * @param byteArray
     * @return Object
     */
    public static <T> T bytes2Object(byte[] byteArray) {
        ObjectInputStream oip = null;
        try {
            oip = new ObjectInputStream(new ByteArrayInputStream(byteArray));
            @SuppressWarnings("unchecked")
            T result = (T) oip.readObject();
            return result;
        }
        catch (IOException e) {
            throw new IllegalArgumentException(e);
        }
        catch (ClassNotFoundException e) {
            throw new IllegalArgumentException(e);
        }
        finally {
            if (oip != null) {
                try {
                    oip.close();
                }
                catch (IOException e) {
                    // eat it
                }
            }
        }
    }


    /**
     * serialize Serializable Object 2 HEX String
     * @param s Object
     * @return String
     */
    public static final String serialize(Serializable s){
        return hex2String(object2Bytes(s));
    }

    /**
     * deserialize 2 Object
     * @param hex String
     * @return Object
     */
    public static final <T> T deserialize(String hex) {
        return bytes2Object(hex2Bytes(hex));
    }

    public static String hex2String(byte[] b) {
        String result = "";
        for (int i = 0; i < b.length; i++) {
            result += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1);
        }
        return result.toUpperCase();
    }

    public static byte[] hex2Bytes(String hex) {
        return hex2Bytes(hex.toCharArray());
    }

    public static byte[] hex2Bytes(char[] hex) {
        int length = hex.length / 2;
        byte[] raw = new byte[length];
        for (int i = 0; i < length; i++) {
            int high = Character.digit(hex[i * 2], 16);
            int low = Character.digit(hex[i * 2 + 1], 16);
            int value = (high << 4) | low;
            if (value > 127) {
                value -= 256;
            }
            raw[i] = (byte) value;
        }
        return raw;
    }
}
